#include "fb_mode.h"

int C_OFB_MODE::Encrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock  = pobjKer->GetBlockLen();
    int& iWrite = *piLenOut;

    iWrite = 0;
    while(iWrite + iBlock <= iLenIn)
    {
        pobjKer->Encrypt(m_bfIV, pOut + iWrite);
        memcpy(m_bfIV, pOut + iWrite, iBlock);
        for(int i = 0; i < 16; i++) pOut[iWrite + i] ^= pIn[iWrite + i];
        iWrite += iBlock;
    }

    return 0;
}

int C_OFB_MODE::Decrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer) { return Encrypt(pIn, iLenIn, pOut, piLenOut, pobjKer); }

int C_CFB_MODE::Encrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock  = pobjKer->GetBlockLen();
    int& iWrite = *piLenOut;

    iWrite = 0;
    while(iWrite + iBlock <= iLenIn)
    {
        pobjKer->Encrypt(m_bfIV, pOut + iWrite);
        for(int i = 0; i < 16; i++) pOut[iWrite + i] ^= pIn[iWrite + i];
        memcpy(m_bfIV, pOut + iWrite, iBlock);
        iWrite += iBlock;
    }

    return 0;
}

int C_CFB_MODE::Decrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock  = pobjKer->GetBlockLen();
    int& iWrite = *piLenOut;

    iWrite = 0;
    while(iWrite + iBlock <= iLenIn)
    {
        pobjKer->Encrypt(m_bfIV, pOut + iWrite);
        for(int i = 0; i < 16; i++) pOut[iWrite + i] ^= pIn[iWrite + i];
        memcpy(m_bfIV, pIn + iWrite, iBlock);
        iWrite += iBlock;
    }

    return 0;
}
